package socketmvc.core.codec;

import socketmvc.core.exception.DecodeBufferLen0Exception;
import socketmvc.core.packets.basic.IPacket;
import socketmvc.core.packets.basic.Protocol;
import socketmvc.core.packets.basic.impl.JsonGzipPacket;
import socketmvc.core.packets.basic.impl.JsonTextBody;
import socketmvc.core.util.BytesUtils;
import socketmvc.core.util.JsonKit;
import java.nio.ByteBuffer;

public class JsonGzipTextContentCodec extends AbstractCodec{

    protected final int HEADER_LENGTH = 5;

    /**
     * 解码
     *
     * @param buffer bytes
     * @return packet
     */
    @Override
    public IPacket decode(ByteBuffer buffer) {
        int position = buffer.position();
        int limit = buffer.limit();
        int readableLength = limit-position;
        // 数据包可读长度小于5，证明数据不够（5代表协议头部有5bytes,1byte协议版本号码，4byte报文内容的长度）
        if (readableLength < HEADER_LENGTH){
            return null;
        }
        byte version = buffer.get(); // 1byte版本号
        int bodyLen = buffer.getInt(); // 消息内容长度
        if (bodyLen <= 0){
            // 抛出协议异常
            throw new DecodeBufferLen0Exception();
        }
        //计算本次需要的数据长度
        int neededLength = HEADER_LENGTH + bodyLen;
        //收到的数据是否足够组包
        int isDataEnough = readableLength - neededLength;

        if (isDataEnough >= 0){//组包成功
            byte[] bodyBytes = new byte[bodyLen];
            buffer.get(bodyBytes);

            return createPacket(bodyBytes);
        }
        return null;
    }

    /**
     * 创建协议包
     * @param bodyBytes 文本内容
     * @return packet
     */
    protected IPacket createPacket(byte[] bodyBytes){
        byte[] unGzipBytes = BytesUtils.decompressGzip(bodyBytes);
        String textBody = BytesUtils.bytesToString(unGzipBytes);
        return new JsonGzipPacket(JsonKit.toBean(textBody, JsonTextBody.class));
    }

    /**
     * 编码
     *
     * @param packet packet
     * @return bytes
     */
    @Override
    public ByteBuffer encode(IPacket packet) {
        byte version = packet.protocolVersion();
        byte[] originBodyBytes = BytesUtils.stringToBytes(packet.getTextBodyAsStr());
        byte[] gzipBodyBytes = BytesUtils.compressGzip(originBodyBytes);
        int bodyLength = gzipBodyBytes.length;

        // 总长度 = 1byte协议版本号 + 4byte正文长度 + n byte 正文内容
        int allLength = HEADER_LENGTH +bodyLength;

        ByteBuffer buffer = ByteBuffer.allocate(allLength);
        buffer.put(version); // 1byte协议版本号
        buffer.putInt(bodyLength); // 4 byte 正文长度
        buffer.put(gzipBodyBytes); // n byte 正文内容
        buffer.rewind();
        return buffer;
    }

    /**
     * 当前解析器所属协议
     *
     * @return 协议对象
     */
    @Override
    public byte protocolVersion() {
        return Protocol.JSON_GZIP_TEXT_CONTENT.getVersion();
    }
}
